Welcome.
In this lecture.
We're going to take a look at how to use module scripts and object oriented programming to create some
house plots that you may or may not have seen in many popular games.
I've attached this model to the lecture, and it's just a small house that has a mailbox and this black
part with it and this black part.
We're going to use to allow a player to claim the house.
And then on the mailbox I have the surface GI that will display the owner's name for this house.
And then there's also a click detector in this front door that the owner of the house can click to lock
and unlock the front door.
Now, before we get started, we need to do a little bit more setup.
We're going to make a folder in the workspace and I'm just going to call it houses and we're going to
set this small house to be a child of this folder.
And then we're also going to need to create a folder in server storage.
I'm going to call it classes.
And then we're going to create a module script in here.
In this module script is going to act as our blueprint or our class for a house object, so I'll just
call it house.
So this is the house class.
Now inside of here, we can just delete this because we're going to need some services or actually we'll
just need one service.
We'll need some variables.
We'll define a constant.
And then this module script is going to contain some private functions or functions that will only be
used within the module script.
And then we're also going to have some public functions and these functions are going to be used when
we create new house objects.
And when we call these functions on these house objects, they'll use the functions that are in this
module script.
So first we need to get access to the player service.
And we're going to be using this later, so don't worry about it for now.
And then the first thing we need to do is create a table because module scripts have to return a table.
So I'm going to call it house and I'm going to use a capital H because this is basically our class and
it's just going to be an empty table.
And then inside of this table, I'm going to set the underscore underscore index meta method to be equal
to the house table.
Now, if you remember in our module script and meta table videos, we set the index meta method to house.
That way when we create a new house object, which is just a table, we're going to attach this house
and this house is going to act as the meta table for our house table.
And the reason we need to do that is because if we call any functions on that house, it's going to
look well, hey, these functions don't exist within this table, but it'll see, hey, there's an index
meta method and it has this house table attached to it.
So then we'll look in this house table and see if there's any functions in there that match whatever
we called on it.
Next thing we're going to do is we're going to declare some functions in here that this class will need.
One is going to be a function for checking whether or not a player owns a house.
So we'll just call it player owns home and we'll pass a player to this function.
We're going to need a function for when the front door gets clicked, so I'll call it on front door
clicked.
And for this function, we're going to have two parameters.
One is going to be called self and then the other is going to be the player that clicked the door.
Now this self is going to represent the house object that this click detector belongs to.
So when the door gets clicked, we can listen and check to see if this player is the owner of the house
by checking a parameter within this table.
And we'll do that in a little bit.
We'll also need a function for when that touch part in the house gets touched.
So we'll call it on claim part touched.
We'll also pass self and we also need to get the part that touched our claim part.
We're just going to need one more function that belongs to the table, and that's going to be our constructor.
So our function will declare one.
So inside of our house table, we're going to declare a new function.
This is going to be our constructor function.
So whenever we need to create a new house object, we're going to call this new function that belongs
to our table and it will return to us a table that represents our house object.
And we're going to pass the model of our house, basically the small house model.
And then the script will take care of everything else for us.
So the first thing I want to do is I want to declare a variable in here and I'm just going to call it
self, but you can name it whatever you'd like.
I'm just going to call it self to stay consistent and it's going to be equal to set meta table.
We're going to pass an empty table.
And we're going to attach the house table to this empty table.
So this this is our house object right here.
This.
This table.
And attached to this table is this other table.
So whenever we try to use any functions on this table.
So, for example, we could do like a function like lock door.
If we call this function on this table, it'll say, Hey, this table right here doesn't have this function
in it.
So let's go ahead and look inside of the meta table to see if it has this function.
And since it will have that function, then it can do all the functionality there.
So inside our house object, we're going to have a few properties.
One, we need to know who the owner of the house is, but for now, we're going to set it to nil.
So there's no owner.
We want the model that belongs to this object, which will be the House model that is passed to this
function.
We need the click detector from this house model so we can do front door click.
This will represent our click detector and we'll use the house model.
And inside this model there's a front door model.
And that front door model has a click detector.
We also need to reference the claim part and again, how model and there's a part in there called claim
part.
And then we also want to access the guy that's on our mailbox.
So I'll call it mailbox guy and it'll be equal to the house model dot mailbox.
And then there's a part in there called label part.
And that label part has a surface guy.
And then we'll need two booleans to keep track of when our front door is locked and when the touch part
has been touched.
So we have a debounce for the touch part.
That way this function can't get run multiple times, so we'll have one be called is front.
Door locked, we'll set it to false and then we'll have one for the bounce.
For our touch part, we'll just call it touched Bounce and we'll set that to false as well.
And then what we need to do now is that when our claim part gets touched.
We're going to connect a function to this.
And inside this function we are going to call the on claim part touched function.
And we need to get the other part that touched our clam part and we need to pass it to this function.
But remember, we also need to pass the table.
Our house object to the function, so we'll just pass self here too.
Now, the reason that I've put this function in here, instead of just copying all the functionality
and pasting it in here is because if I'm creating multiple house objects, that means I'm creating multiple
anonymous functions that all contain the same code.
So it'll take up more memory than if I just have it reference a function that I declared inside the
module script.
So I save on memory that way.
Next, we need to listen to when the front door click detector gets clicked.
So mouse click again, we'll connect a function.
We'll get the player that clicked.
And then we'll just call the on front door clicked.
Pass the door object and the player that clicked the door.
And then I'm pretty sure that's it.
Once we do this, then we simply just want to return this table back to wherever this function was called.
Now, another thing I want to do, actually, is I want to create another variable.
I'm going to call it houses.
It's going to be an empty table.
And I'm going to insert in this table every new house object that gets created.
And I want to do this to be able to check whether or not a player owns a house.
So we need to check through every single house object whether or not a player is a owner of a home.
And the only way to do that is to be able to store these tables inside of this table.
So now that we're done with our constructor, for the most part, we need to create some public functions
for the door class.
So, for example.
For our house object.
We want to be able to set the owner.
Of our house and this function will pass a player to it.
I remember I'm using a colon here because when I create a new house object like self here, if I were
to call this set owner function on it, this self, this table object automatically gets passed to the
function as self.
Self already exists inside of this function because I'm using this colon here.
If I used a dot, I would have to pass self as a parameter in the function, but I just use a colon
and self automatically gets passed.
We'll delete that.
So when we want to set the owner for the house, we'll just do self dot owner is equal to this player.
And then what we could also do is we could access that mailbox guy that we created up here when we first
created our house object.
And inside of that guy, there's a text label.
And we can set the text to something like the players name and then their home so we could do player.name
and then concatenate it with Apostrophe S home so we could do something like Udemy, Lulu courses,
home, whatever.
We'll also need a function for resetting the house.
So let's say a player leaves the game, the owner of the house leaves the game.
Or the owner of the house unclaimed The house.
We want to be able to reset the home, set the owner back to nil, reset the text, all that good stuff.
We'll also have a function for locking the door of the house.
And then we can also have a function for unlocking the door of the house.
And then that's all the functions we'll need in here.
The last thing we need to do in a module script is we need to return the table.
So we need to return house because when a module script gets called, it has to return a table.
And this table contains all of our functions, it contains our constructor, it contains these functions.
And whenever I create a new house object and I call like one of these functions on it because I have
set the index meta method to this table, it'll look and see, Hey, these functions exist within our
house table inside of the meta table.
And I can use them.
So let's go ahead and fill out the rest of these.
For reset, we just want to set the owner of the house back to nil.
And then we also want to reset the mailbox.
Guys text.
So mailbox guy dot text label.
Dot text and actually we can create a constant for it, which is why we declared this little comment
up here.
We'll just call it default.
Text and it will be equal to like, owner name.
Then we can go back down here and set this to default text.
And when we reset the House, we also want to be able to unlock the door so we can just get access to
the house object and call unlock door on it, just like that.
You can kind of see how object oriented programming can be useful or perhaps you could say more logical
in some aspects, but for most people it is a little bit confusing, so don't worry too much if you
if you're still not really understanding.
It's just kind of something you have to practice with over time.
So let's go ahead and fill out these functions.
So what I want to do when I lock the door is I want to set that is front door locked boolean to true.
So that way we know the front door is locked.
And then what we could do is we could loop through every single part or object that is within that front
door model.
So we'll do any pairs, we'll do self dot model to get the house, we'll get the front door and then
we're going to get every single descendant of that door and then we'll check if this object.
Is not a bass part, so is a bass part.
Then we'll just continue looping until we find a object that is a base part.
And when it is, we'll set object dot can collide equal to true.
So we can't walk through the door.
And then we can just basically copy and paste this in here and just set this to false.
You could put this in another function since we're technically copying and pasting code here, but I'm
just going to leave it like that because it really isn't that much code.
So the next thing we need to do is to fill out these private functions.
But for this one, we need to check if a player owns a home.
And the easy way to do that is because we're saving every single house object in this table.
We'll just loop through every single one of them.
So for every single house object that is in the table houses, we'll check if the house object dot owner.
Right.
This property we made down here.
If it's not equal to the player that gets passed to this function, then we're just going to continue.
Otherwise, if we do find a house object that a player owns, we'll return.
True.
Otherwise, if we finish through this entire loop and we find no house object that the player owns,
we'll return false.
And we're going to be using this function in a moment.
The next thing we want to do is fill out this function.
So what do we want to happen when the front door is clicked?
Well, the first thing we need to check is if the player that activated this click detector is equal
to the self dot owner, the owner of the house object.
If he isn't the owner.
Then we'll just return because only the owner can unlock and lock the front door.
Otherwise we can check if self is front door locked.
Oops.
If the front door is locked, then we want to do.
Unlock a door.
Right.
Unlock the door inside of our house object.
Otherwise we can lock the door.
And that's it for that.
Now we can listen here for when the claim part gets touched.
So the first thing we want to check is we want to see if whatever touched our part is a player belongs
to a player.
So we could do we could do local player is equal to and this is why we reference the player service
we're going to use a function called get player from character.
We'll get the player from their character model and we'll pass other part dot parent.
So let's say if their left foot touched the part or their leg or whatever, we get the parent of that
leg, which should be the character model.
And if that character model belongs to a player, we'll get the player right here.
Otherwise, if there is no player, then we'll just return.
But if there is a player, then we're going to use the player owns home function.
So if this player already owns a home.
Right.
And we also have to check if the player isn't the owner of this home in particular that the claim part
got touched on.
So self dot owner.
Then we're going to return.
Because if a player already owns a home, we don't want them to own another one, but we also want them
to be able to claim a home by touching that part again.
So we have to make sure.
That this player also doesn't own this home that they're touching.
Next, we can check if the self touched debounce is true.
If it is, we're going to return.
And then we're going to use a function from the task library.
Task dot delay.
We're going to delay a function from running.
We'll wait like three seconds.
And all this function is going to do is set self dot touch debounce back to false.
So we have a three second cooldown on that touch part.
Now that we have all of that done, we can check if this house has a owner.
So if self dot owner.
And the player is the owner of the house that touched this part.
Then that means they want to claim the house.
So we can call that self reset function on it.
Reset.
We reset the house.
There's no more owner and all is well.
Otherwise, if the house doesn't have an owner.
So.
If there is no owner for the house, then we're going to self.
We're going to call the function set owner and the owner is going to be this player.
Otherwise, if the players already owned and another player is trying to claim it, then we're just
not going to do anything.
So this looks pretty good here.
I don't think there's actually anything else we need to do.
But as always, I'm going to explain the script one more time just to make sure you understand everything
that's going on.
So the purpose of this module script is to act as a blueprint for creating a new house object.
All right.
This gives us the blueprint.
Everything we need to create a new house object, and we create a new house object.
Using this constructor, it creates a new empty table with the class attached to it as a meta table.
We set all sorts of properties in this table, such as the owner.
What the model of the object is, you know, the click detector and all this other stuff, as well as
attaching some functions to events.
That way whenever we call a function on this table.
It's going to see, Hey, there's a metal table and this metal table has an index meta method, which
is the house class.
And this house class contains all of the functions we need for our house.
So if I ever wanted to set the owner for this object, if I ever wanted to open or I mean lock or unlock
the door, then I can do it because I attached.
This metal table.
Now, once we have this object created, we can do whatever we want with the table.
Right.
We can set the owner for the table.
We can reset the house object, set the owner to nil, reset the text on our guy, unlock the door.
We can lock the door, and then we can listen to when parts get touched in our house to set the owner
of the house or reset the house.
We can listen for when the front door gets clicked by the owner to lock or unlock it and all that kind
of good stuff.
You can really fill this up with whatever functionality you want for the house.
But before we can even use this module script, we need to require it in a server script.
So let's go to server script service.
We will create a new script and this script will be called.
We'll just call it house class handler.
And inside of here, we're going to need some services.
We need the server storage service because that's where our module script is stored.
So server storage.
And we'll also need the player service and you'll see why in a moment.
We're going to need a couple variables.
First, we need to get the house class.
So we'll call it house class.
And we need to require the module script.
We need to require this module script.
So we do server storage classes, the classes folder and get the house module script.
So because we've required the module script, all the code in here gets ran and at the very end we return
the house table, which gets stored inside of this variable.
And what does that mean?
Well, that means we can access the functions inside this table like.new and we can pass our house model
to it.
All righty.
Hey there.
This is me from the Future.
And fortunately, my software decided to not record my voice anymore.
But I'm just going to overview what I think I was saying earlier.
So what we're going to do here is we're going to make a simple change to this variable.
We're actually going to make it belong to the house table itself in the module script.
And of course you're going to have to replace that reference in several areas in the module script.
But the reason we're doing that is so we're able to access that table from our server script, and that's
going to be very important for us to do here.
You'll see why in a little bit.
Otherwise we're going to create a handler to listen to an event.
And that event is going to be when a player gets removed from our game.
So we'll connect a lambda function to it and get that player that left the game.
Now, the reason we need to get the player who left the game is to check to see whether or not they
owned a house.
Because if they did own a house, well, we need to reset that house.
So we're going to loop through every single table.
That is in our house.
Class houses, table.
All those house objects.
We need to loop through those and check to see if the owner is the player that left the game.
If it isn't, we're just going to continue looping until we find a table that the player might have
owned.
So in this case, if the player was the owner of this house object, then we need to reset the house.
Now, one more thing we need to do is that we have to create all of these house objects in the first
place, right.
We need to create all of the house objects.
So we're going to loop through every single house model that is in that houses folder in the workspace.
So we're going to get that houses folder.
We're going to get all the children, all of those house models.
And then we're going to use the constructor in our module script to create these new objects.
So we reference our house class, pass the new function or call the new function and we pass our house
model.
And that creates the new house object for us which will exist in that houses table.
Now, before we go and test our houses, there's actually an error we need to fix inside of our game
and we need to fix a reference here within our module script.
But now we are in our game and we can go and touch the part and it should update the name on our mailbox.
And as you can see, we have a little problem there.
And the reason is, is that we forgot to set that touch debounce to true within our module script.
So we're going to fix that real quick as well.
We also need to fix the git descendants function because I accidentally put.
Git descendant instead of git descendants.
But now that we have fixed those problems, if we go and touch on that brick, it's going to update
the mailbox name to us.
There we go.
Udemy Louis courses home.
And that also means we can go up and lock and unlock our door.
So if I click, I lock it.
If I click again, I can unlock the door.
And I'm the only one who has the ability to do this.
Now, if I want to claim my house, I can just touch the part again.
And as you can see, the text on the mailbox gets reset and I won't be able to lock the door anymore.
It will stay unlocked until someone else claims the house.
Now because we've scripted our game in this way or our house objects in this way, we can actually duplicate
as many of these house objects as we want.
Because they were all belonged to separate house objects that are created from our module script.
So back in my game, I can go ahead and claim any one of these houses, and if I go and try to claim
another house, it won't let me claim it because I already own that other house.
But if I unclaimed my house, I can go back, run over here and claim this new house just like that.
And I have the ability to lock and unlock the door.
So as you can see, object oriented programming inside of Lua, you can be quite interesting and actually
helpful if you understand it and implement it properly.
Hopefully this video helped you understand one way of creating a house plot system.
Otherwise I will see you in the next lecture.